home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD ROM Paradise Collection 4
/
CD ROM Paradise Collection 4 1995 Nov.iso
/
arcers
/
tar316.zip
/
SAVEFILE.C
< prev
next >
Wrap
Text File
|
1994-07-21
|
11KB
|
400 lines
/* savefile.c - storying regular files into (tape) archive
* This is the part of the Tar program (see file tar.c)
* Author: T.V.Shaporev
* Creation date 11 Mar 1993
*/
#include <stdio.h>
#include "sysup.h"
#include "modern.h"
#include "compress.h"
#include "zippipe.h"
#include "crc32.h"
#include "define.h"
extern char longname[];
extern char *deleft __ARGS__(( char * ));
extern void newhead __ARGS__(( char *, long ));
extern void prcsum __ARGS__(( register header * ));
extern void proctl __ARGS__(( char *, long ));
static void prhexl __ARGS__(( char *, long ));
static void prhexl(dest, l)
char *dest; long l;
{
register int i;
static char h[] = "0123456789AbCdEf";
*dest++ = '0'; *dest++ = 'x';
for (i=32; i;) *dest++ = h[(int)(l >> (i -= 4)) & 15];
*dest++ = ' '; *dest++ = '\0';
}
#ifdef UNIX
static werelost = FALSE;
#endif
#ifdef MSDOS
# include <string.h>
# ifdef __TURBOC__
# include <dir.h>
# else
# include <direct.h>
# endif
# include <io.h>
static int skipdots __ARGS__(( char *, int ));
static int unperiod __ARGS__(( char *, int ));
static int nextchar __ARGS__(( char *, int ));
static int skipdots(char *s, int n)
{
while (n>0 && s[n]=='/' && s[n-1]=='.' && (n<2 || s[n-2]=='/'))
n -= 2;
return n;
}
static int unperiod(char *s, int n)
{
while (n>2 && s[n]=='/' && s[n-1]=='.' && s[n-2]=='.' && s[n-3]=='/') {
if ((n -= 3) > 0) {
for (n=nextchar(s, n); n>=0 && s[n]!='/'; n--) ;
}
}
return n;
}
static int nextchar(char *s, int n)
{
if (n >= 0) n -= 1;
while (n>0 && s[n]=='/' && s[n-1]=='.' &&
((n<2 || s[n-2]=='/') ||
n>2 && s[n-2]=='.' && s[n-3]=='/')) {
if (n>1 && s[n-2]=='.') {
n = unperiod(s, n);
} else {
n = skipdots(s, n);
}
}
return n;
}
#else
int strlen();
char *strcpy(), *strcat(), *strncpy();
int open(), read(), close(), unlink();
long lseek();
#endif
#include "lzpack.h"
#include "roll.h"
void cantopen(name)
char *name;
{
(void)fprintf(myout, "Tar: can\'t open \'%s\'\n", name);
}
static void tmpput __ARGS__(( int ));
static void no_mem __ARGS__(( int ));
static void errproc __ARGS__(( char * ));
static void tmpput(c)
int c;
{
++codesize; if (rputc(c) != 0) errproc(hblock->m.name);
}
static void no_mem(flag)
int flag;
{
(void)fprintf(stderr, "No memory for encoding.");
if (flag) {
(void)fprintf(stderr, " Continue? ");
if (YES_NO()) return;
} else {
(void)fprintf(stderr, "\n");
}
done(ESMALL);
}
static void errproc(fname)
char *fname;
{
(void)fprintf(myout, "\nTar: error processing \'%s\'\n", fname);
done(EINTER);
}
void savefile(fname)
char *fname;
{
register i; register c;
register char *p;
register long blocks;
register packok;
register struct node *t; struct node *prev;
int infile; long this;
p = deleft(fname);
if (u_flag) {
if ((t = finditem(p, &prev, timehead)) != NONE) {
i = t->info.time >= st.st_mtime;
delitem(t, &timehead);
if (i) return;
}
}
if (isfile) {/* compare file to store with the archive one */
#ifdef UNIX
if (st.st_ino == sa.st_ino && st.st_dev == sa.st_dev) return;
#endif
#ifdef MSDOS
/* The following comparison algorithm may fail */
/* on combination of substed and real drives */
register char *p1, *p2;
register j1, j2;
register d2;
char b[2*MAXPATH];
if (st.st_dev != sa.st_dev) goto next;
/* Sinse 'st_dev' field gives the real drive number */
/* there is no need to compare drive names */
j1 = strlen(p1 = archname);
p2 = fname;
if (p2[0]>='a' && p2[0]<='z' && p2[1]==':') {
d2 = p2[0] - ('a'-1);
p2 += 2;
} else {
d2 = 0;
}
j2 = strlen(p2);
while (j1>0 && p1[j1-1]!='/' && j2>0 && p2[j2-1]!='/') {
if (p1[--j1] != p2[--j2]) goto next;
}
if (p2[0] != '/') {
*(int *)b = '/';
(void)getcurdir(d2, b+1);
takename(b, b);
i = strlen(b);
b[i++] = '/';
strcpy(b+i, p2);
p2 = b;
j2 += i;
}
do {
j1 = nextchar(p1, j1);
j2 = nextchar(p2, j2);
if (j1 >= 0 && j2 >= 0 && p1[j1] != p2[j2]) goto next;
} while (j1>=0 && j2>=0);
if (j1 == j2) return;
#endif
}
#ifdef MSDOS
next: i = st.st_mode & 0700; st.st_mode |= (i>>3)|(i>>6);
#endif
if (w_flag && !okwork('a', ' ', &st, fname)) return;
if ((infile = open(fname, O_RDONLY+O_BINARY)) < 0) {
cantopen(fname); return;
}
newhead(fname, st.st_size);
#ifdef UNIX
if (st.st_nlink > 1) {
prev = t = linkhead; i = 1;
while (t && i>0) {
i = st.st_ino - t->info.data.inode;
if (!i) i = st.st_dev - t->info.data.device;
if (i>0) { prev = t; t = t->next; }
}
if (i || !t) {/* entry not found */
if ((t = additem(p, prev, &linkhead)) == NONE) {
if (!werelost) {
(void)fprintf(myout,
"Tar: out of memory; link(s) lost\n");
werelost = TRUE;
}
} else {
t->info.data.count = st.st_nlink - 1;
t->info.data.device = st.st_dev;
t->info.data.inode = st.st_ino;
}
} else {/* previous entry found */
(void)strncpy(hblock->m.linkname, t->name, MAXTNAME);
hblock->m.filetype = TF_LNK;
prcsum(hblock);
if (v_flag) {
(void)fprintf(myout, "a %s link to %s\n", p, t->name);
}
if (--(t->info.data.count) < 1) delitem(t, &linkhead);
(void)close(infile);
return;
}
}
#endif
blocks = (st.st_size + (BLKSIZE-1)) / BLKSIZE;
packok = FALSE;
if (blocks > 1) {
if (pktype == PKDEF) {
if (zipalloc()!=0 || newroll("TAROLLXXXXXX")!=0) {
delroll();
#ifndef MSDOS
if (!w_flag) {
no_mem(0);
} else
#endif
{
no_mem(1);
pktype = PKNONE;
goto run;
}
}
(void)rewroll(0);
if (v_flag) (void)fprintf(stderr, "e %s", p);
(void)fflush(stderr);
if (zipcreat(tmpput, ZIP_RAW, pklevel) != 0) {
(void)fprintf(stderr, "Zip error: %s\n", ziperrlist[ziperror]);
done(EINTER);
}
this = 0;
do {
if ((i = read(infile, pk_inp, pksize)) < 0) {
errproc(hblock->m.name);
}
if (i > 0) {
(void)zipwrite(pk_inp, i);
if (v_flag) percent((this += i), st.st_size);
}
} while (i == pksize);
codesize = zipclose();
}
#ifdef USE_COMPRESS
else if (pktype == PKfLZW) {
if (strlen(hblock->m.name) > MAXTNAME-2) {
#ifndef MSDOS
if (!w_flag) {
(void)fprintf(stderr, longname, hblock->m.name, "\n");
} else
#endif
{
(void)fprintf(stderr, longname, hblock->m.name,
" Store uncompressed? ");
if (YES_NO()) goto run;
}
return;
}
if (newroll("TAROLLXXXXXX")!=0) {
delroll();
#ifndef MSDOS
if (!w_flag) {
no_mem(0);
} else
#endif
{
no_mem(1);
pktype = PKNONE;
goto run;
}
}
if ((i = z_gettab(pklevel)) < pklevel) {
if (pklevel > 0) {
#ifndef MSDOS
if (!w_flag) {
(void)fprintf(stderr, "Can only handle %d bits.\n", i);
} else
#endif
{
(void)fprintf(stderr,
"Can only handle %d bits. Continue? ", i);
pklevel = YES_NO() ? i : -1;
}
}
if (pklevel <= 0) {
no_mem(1);
z_reltab();
pktype = PKNONE;
goto run;
}
}
(void)rewroll(0);
if (v_flag) (void)fprintf(stderr, "z %s", p);
(void)fflush(stderr);
if (cbegin(pklevel, tmpput, st.st_size) < pklevel) no_mem(0);
this = 0;
do {
if ((i = read(infile, pk_inp, pksize)) < 0) {
errproc(hblock->m.name);
}
if (i > 0) {
cpiece(pk_inp, i);
if (v_flag) percent((this += i), st.st_size);
}
} while (i == pksize);
codesize = cflush();
}
#endif
if (v_flag) (void)fprintf(stderr, "\r");
if (pkfile) {
register long b;
if ((b = (codesize + (BLKSIZE-1)) / BLKSIZE) < blocks) {
packok = TRUE;
blocks = b;
} else if (lseek(infile, 0L, 0) < 0) {
(void)fprintf(myout, "Tar: \'%s\' seek error\n", fname);
done(ERREAD);
}
}
}
run : if (v_flag || j_flag) {
(void)fprintf(myout, "a %s %ld blocks\n", p, blocks);
}
if (j_flag) {
(void)fprintf(stderr, "> ");
for (i=0; (c=getc(myinp))!='\n'; ) {
if (i < sizeof(hblock->m.comment)-1) {
hblock->m.comment[i++] = c;
}
}
hblock->m.comment[i] = 0;
} else {
hblock->m.comment[0] = 0;
}
if (packok) {
proctl(hblock->m.size, codesize);
if (pktype == PKfLZW) {
(void)strcat(hblock->m.name, ".Z");
} else { /* pktype == PKDEF */
prhexl(hblock->m.srcsum, getcrc());
prhexl(hblock->m.srclen, st.st_size);
}
prcsum(hblock);
if (rewroll(1) != 0) errproc(p);
while (codesize-- > 0) {
if ((c = rgetc()) == EOF) errproc(p);
writebyte(c);
}
} else {/* common store file */
prcsum(hblock);
if ((blocks -= writearch(infile, st.st_size, fname)) != 0) {
(void)fprintf(myout, "Tar: \'%s\' decreased size\n", fname);
while (blocks-- > 0) nullblock(steptape());
}
}
(void)close(infile);
if (y_flag) {
#ifdef MDSOS
if (!(st.st_mode & S_IWRITE)) (void)chmod(fname, S_IWRITE);
#endif
if (unlink(fname)) {
(void)fprintf(myout, "Tar: can\'t delete \'%s\'\n", fname);
}
}
}